package manager

import (
	"happy-sudoku/internal/model"
	"happy-sudoku/internal/repository"
)

type IPlayerManager interface {
	Exist(playerID int) bool
	// Player State Update
	GetPlayerState(playerID int) (*model.PlayerState, error)
	DeletePlayerState(playerID int) error
	UpdatePlayerState(playerID int, state model.PlayerState) (*model.PlayerState, error)
	UpdateStatus(playerID int, status model.Status) (*model.PlayerState, error)
	UpdateLocation(playerID int, location model.PlayerLocation) (*model.PlayerState, error)
	UpdateProgress(playerID int, progress float64) (*model.PlayerState, error)
	UpdateGameScore(playerID int, score int) (*model.PlayerState, error)
}

type PlayerManager struct {
	playerRepo repository.IPlayerRepo
	stateRepo  repository.IPlayerStateRepo
}

func NewPlayerManager(pr repository.IPlayerRepo, sr repository.IPlayerStateRepo) *PlayerManager {
	return &PlayerManager{
		playerRepo: pr,
		stateRepo:  sr,
	}
}

func (p *PlayerManager) Exist(playerID int) bool {
	player, _ := p.playerRepo.GetOne(playerID)
	if player != nil {
		return true
	}
	return false
}

// Player State Update
func (p *PlayerManager) GetPlayerState(playerID int) (*model.PlayerState, error) {
	return p.stateRepo.GetOne(playerID)
}

func (p *PlayerManager) DeletePlayerState(playerID int) error {
	return p.stateRepo.Delete(playerID)
}

func (p *PlayerManager) UpdatePlayerState(playerID int, state model.PlayerState) (*model.PlayerState, error) {
	err := p.stateRepo.Update(playerID, state)
	if err != nil {
		return nil, err
	}
	return &state, nil
}

func (p *PlayerManager) UpdateStatus(playerID int, status model.Status) (*model.PlayerState, error) {
	state, err := p.stateRepo.GetOne(playerID)
	if err != nil {
		return nil, err
	}
	state.Status = status
	return p.UpdatePlayerState(playerID, *state)
}

func (p *PlayerManager) UpdateLocation(playerID int, location model.PlayerLocation) (*model.PlayerState, error) {
	state, err := p.stateRepo.GetOne(playerID)
	if err != nil {
		return nil, err
	}
	*state.Location = location
	return p.UpdatePlayerState(playerID, *state)
}

func (p *PlayerManager) UpdateProgress(playerID int, progress float64) (*model.PlayerState, error) {
	state, err := p.stateRepo.GetOne(playerID)
	if err != nil {
		return nil, err
	}
	state.Progress = progress
	return p.UpdatePlayerState(playerID, *state)
}

func (p *PlayerManager) UpdateGameScore(playerID int, score int) (*model.PlayerState, error) {
	state, err := p.stateRepo.GetOne(playerID)
	if err != nil {
		return nil, err
	}
	state.GamingScore = score
	return p.UpdatePlayerState(playerID, *state)
}
